package de.uni_saarland.coli.doclists.data.btree;

import java.io.Serializable;

import de.uni_saarland.coli.doclists.data.btree.manager.IBTreeNodeManager;
import de.uni_saarland.coli.doclists.index.IDiscIO;

/**
 * 
 * @author stefan
 * 
 *         The B+ Tree.
 * 
 * @param <T>
 *            The type of data.
 */
@SuppressWarnings("rawtypes")
public class BTree<T> implements IMapData<T>, IDiscIO, Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -7630683076103392586L;

	/**
	 * the root node
	 */
	private INode<T> root;

	/**
	 * the node manager
	 */
	private static IBTreeNodeManager nodeManager;

	/*
	 * Constructor.
	 */
	public BTree() {
		this.root = null;
	}

	@SuppressWarnings("unchecked")
	/**
	 * Initializes the tree.
	 * @param nodeFactory the node factory.
	 */
	public void initialize(IBTreeNodeManager<T> nodeFactory) {
		BTree.nodeManager = nodeFactory;
		this.root = BTree.nodeManager.createBucketNode();

	}

	/**
	 * Returns the node manager.
	 * 
	 * @return the node manager
	 */
	public static IBTreeNodeManager getNodeFactory() {
		return BTree.nodeManager;
	}

	/**
	 * Adds a key value pair to the tree.
	 * 
	 * @param key
	 *            the key
	 * @param value
	 *            the value returns the value
	 */
	@SuppressWarnings("unchecked")
	public T add(int key, T value) {
		try {
			// System.out.println("add " + key);
			// System.out.println(this.root);
			SplitData<T> splitData = this.root.addData(key, value);

			if (splitData != null) {
//				 System.out.println("split");
//				 System.out.println("LEFT:");
//				 System.out.println(splitData.getLeft());
//				 System.out.println("Right:");
//				 System.out.println(splitData.getRight());
//				 System.out.println("------");
				 System.out.println("key " + splitData.getKey());
				 System.out.println("LEFT " + splitData.getLeft().getNodeID());
				 System.out.println(splitData.getLeft());
				 System.out.println("RIGHT " + splitData.getRight().getNodeID());
				 System.out.println(splitData.getRight().toString());
				 System.out.println("++++");

				this.root = BTree.nodeManager.createNonBucketNode(splitData);
				System.out.println("yyy");
//				System.out.println("rrrrrrr " + this.root.getNodeID());
//				System.out.println(this.root);
			}
			// System.out.println("Tree");
			// System.out.println(this.root.toString());
			// System.out.println("------");
			return value;
		} catch (NullPointerException e) {
			throw new RuntimeException("not initalized");

		}
	}

	/**
	 * Returns the value given a key.
	 * 
	 * @param key
	 *            the key return the value
	 */
	public T get(int key) {
		return this.root.get(key);
	}

	@Override
	public boolean containsKey(int key) {
		return null != this.root.get(key);
	}

	@Override
	public String toString() {
		if (this.root != null)
			return this.root.toString();
		else
			return "";
	}

	@Override
	public void save(String path, String baseName) {
		BTree.nodeManager.save(path, baseName);
	}

	@Override
	public void open(String path, String baseName) {
		BTree.nodeManager.open(path, baseName);
	}
}
